home *** CD-ROM | disk | FTP | other *** search
/ 3D Games - Real-time Rend…ng & Software Technology / 3D Games - Real-time Rendering & Software Technology.iso / flysdk / lib / flyEngine / flyEngine.cpp < prev    next >
Encoding:
C/C++ Source or Header  |  2001-03-05  |  45.8 KB  |  2,500 lines

  1. #include "../Fly3D.h"
  2.  
  3. FLY_API flyEngine *flyengine=0;
  4. FLY_API HWND hFlyWnd=0;
  5. FLY_API HINSTANCE hFlyInst=0;
  6.  
  7. FLY_API void init_engine(HWND hWnd,HINSTANCE hInst,int appid)
  8. {
  9.     free_engine();
  10.     set_engine(new flyEngine,hWnd,hInst,appid);
  11. }
  12.  
  13. FLY_API void set_engine(flyEngine *eng,HWND hWnd,HINSTANCE hInst,int appid)
  14. {
  15.     flyengine=eng;
  16.     flyengine->appid=appid;
  17.     hFlyWnd=hWnd;
  18.     hFlyInst=hInst;
  19. }
  20.  
  21. FLY_API void free_engine()
  22. {
  23.     if (flyengine)
  24.         delete flyengine;
  25.     flyengine=0;
  26. }
  27.  
  28. BOOL APIENTRY DllMain( HANDLE hModule, 
  29.                        DWORD  ul_reason_for_call, 
  30.                        LPVOID lpReserved
  31.                      )
  32. {
  33.     switch (ul_reason_for_call)
  34.     {
  35.         case DLL_PROCESS_ATTACH:
  36.         case DLL_THREAD_ATTACH:
  37.         case DLL_THREAD_DETACH:
  38.         case DLL_PROCESS_DETACH:
  39.             break;
  40.     }
  41.     return TRUE;
  42. }
  43.  
  44. flyEngine::flyEngine()
  45. {
  46.     cur_step=cur_step_base=0;
  47.     cur_frame=cur_frame_base=0;
  48.     start_time=cur_time=cur_dt=0;
  49.     intropic=introtime=0;
  50.  
  51.     player=0;
  52.     cam=0;
  53.     excludecollision=0;
  54.     stepobj=0;
  55.  
  56.     nelemdraw=0;
  57.     facedraw=0;
  58.     nfacedraw=0;
  59.     facedrawtransp=0;
  60.     nfacedrawtransp=0;
  61.  
  62.     status_msg_time=0;
  63.         
  64.     bboxdiag=viewmaxdist=viewmindist=camangle=aspect=geomdetail=
  65.         curveerr=lmpxsize=detailtile=cartoonwidth=shadowdepth=0;
  66.     
  67.     nodedrawcount=nodeonly=pvsoff=fog=mpdelay=antialias=
  68.         amblight=mapmode=shadows=noinput=wireframe=mute=mouse=
  69.         clearbk=moving=crosshairpic=crosshairsize=appid=multitexture=
  70.         detailpic=hwlights=stencil=cartoonpic=cartoonpicbsp=0;
  71.  
  72.     active_obj0=last_active_obj=0;
  73.     stock_obj0=0;
  74.     model_obj0=0;
  75.     sound_obj0=0;
  76.     bezier_curve0=0;
  77.     bezier_patch0=0;
  78.     shadow_obj=0;
  79.     hitobj=0;
  80.     hitmesh=0;
  81.     hitface=0;
  82.  
  83.     status=0;
  84.     fontspic=0;
  85.     consolepic=0;
  86.  
  87.     vert=vertcolor=vertnormal=0;
  88.     nvert=0;
  89.  
  90.     faces=0;
  91.     nfaces=0;
  92.  
  93.     edges=0;
  94.     nedges=0;
  95.     faceedges=0;
  96.  
  97.     bsp=0;
  98.     npiclib=0;
  99.     nlm=lmbase=nlmpic=0;
  100.     fmbase=0;
  101.  
  102.     pvs=0;
  103.     leaf=0;
  104.     nleaf=pvssize=pvsrowsize=0;
  105.     
  106.     reset();
  107.  
  108.     appid=FLYAPPID_NONE;
  109.     start_time=timeGetTime();
  110.  
  111.     strcpy(flysdkpath,GetCommandLine());
  112.     if (flysdkpath[0]=='\"')
  113.     {
  114.         strcpy(flysdkpath,&flysdkpath[1]);
  115.         if (strchr(flysdkpath,'\"')) 
  116.             *strchr(flysdkpath,'\"')=0;
  117.     }
  118.     if (strrchr(flysdkpath,'\\'))
  119.         *(strrchr(flysdkpath,'\\')+1)=0;
  120.     else 
  121.     {
  122.         GetCurrentDirectory(255,flysdkpath);
  123.         strcat(flysdkpath,"\\");
  124.     }
  125.     strlwr(flysdkpath);
  126. }
  127.  
  128. void flyEngine::reset()
  129. {
  130.     int i;
  131.     bsp_object *d;
  132.     mesh *o;
  133.     sound *s;
  134.     bezier_curve *c;
  135.     bezier_patch *p;
  136.  
  137.     while(active_obj0)
  138.         {
  139.         d=(bsp_object *)active_obj0->next_obj;
  140.         delete active_obj0;
  141.         active_obj0=d;
  142.         }
  143.     last_active_obj=0;
  144.     while(stock_obj0)
  145.         {
  146.         d=(bsp_object *)stock_obj0->next_obj;
  147.         delete stock_obj0;
  148.         stock_obj0=d;
  149.         }
  150.     while(model_obj0)
  151.         {
  152.         o=(mesh *)model_obj0->next_obj;
  153.         delete model_obj0;
  154.         model_obj0=o;
  155.         }
  156.     while(sound_obj0)
  157.         {
  158.         s=(sound *)sound_obj0->next_obj;
  159.         delete sound_obj0;
  160.         sound_obj0=s;
  161.         }
  162.     while(bezier_curve0)
  163.         {
  164.         c=(bezier_curve *)bezier_curve0->next_obj;
  165.         delete bezier_curve0;
  166.         bezier_curve0=c;
  167.         }
  168.     while(bezier_patch0)
  169.         {
  170.         p=(bezier_patch *)bezier_patch0->next_obj;
  171.         delete bezier_patch0;
  172.         bezier_patch0=p;
  173.         }
  174.  
  175.     if (bsp) 
  176.         delete bsp;
  177.     bsp=0;
  178.  
  179.     if (vert)
  180.         delete vert;
  181.     vert=0;
  182.  
  183.     if (vertnormal)
  184.         delete vertnormal;
  185.     vertnormal=0;
  186.  
  187.     if (vertcolor)
  188.         delete vertcolor;
  189.     vertcolor=0;
  190.  
  191.     if (faces)
  192.         delete faces;
  193.     faces=0;
  194.  
  195.     if (edges)
  196.         delete edges;
  197.     edges=0;
  198.  
  199.     if (faceedges)
  200.         delete faceedges;
  201.     faceedges=0;
  202.  
  203.     nvert=0;
  204.     nfaces=0;
  205.     nedges=0;
  206.  
  207.     if (npiclib)
  208.         for( i=0;i<npiclib;i++ )
  209.             delete piclib[i];
  210.     npiclib=0;
  211.  
  212.     if (pvs)
  213.         delete pvs;
  214.     pvs=0;
  215.     pvssize=0;
  216.     pvsrowsize=0;
  217.  
  218.     if (leaf)
  219.         delete leaf;
  220.     leaf=0;
  221.     nleaf=0;
  222.  
  223.     if (facedraw)
  224.         delete facedraw;
  225.     facedraw=0;
  226.  
  227.     if (facedrawtransp)
  228.         delete facedrawtransp;
  229.     facedrawtransp=0;
  230.  
  231.     for( i=0;i<nlmpic;i++ )
  232.         {
  233.         delete lmpic[i];
  234.         delete fmpic[i];
  235.         }
  236.     for( i=0;i<nlm;i++ )
  237.         {
  238.         delete lm[i];
  239.         delete fm[i];
  240.         }
  241.     nlm=0;
  242.     nlmpic=0;
  243.     lmbase=0;
  244.     fmbase=0;
  245.  
  246.     dll.reset();
  247.  
  248.     fontspic=-1;
  249.     crosshairpic=-1;
  250.     detailpic=-1;
  251.     intropic=-1;
  252.     consolepic=-1;
  253.     cartoonpicbsp=-1;
  254.     cartoonpic=-1;
  255.  
  256.     bspfile[0]=0;
  257.     flydatapath[0]=0;
  258.     flyfile[0]=0;
  259.     flyfilename[0]=0;
  260.     console_command[0]=0;
  261.     status_msg[0]=0;
  262.     status_msg_time=0;
  263.  
  264.     nodedrawcount=nfacedraw=nfacedrawtransp=0;
  265.  
  266.     cur_frame=cur_frame_base=0;
  267.     cur_step=cur_step_base=0;
  268.     cur_time=cur_dt=0;
  269.  
  270.     filter.vec(0,0,0);
  271.     background.vec(0,0,0);
  272.     clearbk=1;
  273.     introtime=2000;
  274.  
  275.     cam=0;
  276.     player=0;
  277. }
  278.  
  279. void flyEngine::compute_normals()
  280. {
  281.     // simple and fast vertex normals
  282.     int i,j;
  283.     if (vertnormal)
  284.         delete vertnormal;
  285.     vertnormal=new vector[nvert];
  286.     memset(vertnormal,0,sizeof(vector)*nvert);
  287.     for( j=0;j<nfaces;j++ )
  288.     {
  289.         vertnormal[faces[j].vert[0]-vert]+=faces[j].normal;
  290.         vertnormal[faces[j].vert[1]-vert]+=faces[j].normal;
  291.         vertnormal[faces[j].vert[2]-vert]+=faces[j].normal;
  292.     }
  293.     for( i=0;i<nvert;i++ )
  294.         vertnormal[i].normalize();
  295.  
  296.     for( i=0;i<nfaces;i++ )
  297.         for( j=0;j<3;j++ )
  298.             faces[i].vertnormal[j]=vertnormal[faces[i].vert[j]-vert];
  299. /*
  300.     // more accurate and slower vertex normals
  301.     if (vertnormal)
  302.         delete vertnormal;
  303.     vector *nn=new vector[nfaces];
  304.     vertnormal=new vector[nvert];
  305.     int i,j,k,nc;
  306.     for( i=0;i<nvert;i++ )
  307.         {
  308.         nc=0;
  309.         for( j=0;j<nfaces;j++ )
  310.             if (faces[j].vert[0]==&vert[i] ||
  311.                 faces[j].vert[1]==&vert[i] ||
  312.                 faces[j].vert[2]==&vert[i])
  313.                 {
  314.                 for( k=0;k<nc;k++ )
  315.                     if (vec_dot(faces[j].normal,nn[k])>0.999848f)
  316.                         break;
  317.                 if (k==nc)
  318.                     nn[nc++]=faces[j].normal;
  319.                 }
  320.         vertnormal[i].null();
  321.         if (nc)
  322.             {
  323.             for( k=0;k<nc;k++ )
  324.                 vertnormal[i]+=nn[k];
  325.             vertnormal[i].normalize();
  326.             }
  327.         }
  328.     for( i=0;i<nfaces;i++ )
  329.         for( j=0;j<3;j++ )
  330.             faces[i].vertnormal[j]=vertnormal[faces[i].vert[j]-vert];
  331.     delete nn;
  332. */
  333.     // bound box
  334.     bbox1.vec(BIG,BIG,BIG);
  335.     bbox2.vec(-BIG,-BIG,-BIG);
  336.  
  337.     for( i=0;i<nvert;i++ )
  338.     {
  339.         if (vert[i].x>bbox2.x)
  340.             bbox2.x=vert[i].x;
  341.         if (vert[i].y>bbox2.y)
  342.             bbox2.y=vert[i].y;
  343.         if (vert[i].z>bbox2.z)
  344.             bbox2.z=vert[i].z;
  345.  
  346.         if (vert[i].x<bbox1.x)
  347.             bbox1.x=vert[i].x;
  348.         if (vert[i].y<bbox1.y)
  349.             bbox1.y=vert[i].y;
  350.         if (vert[i].z<bbox1.z)
  351.             bbox1.z=vert[i].z;
  352.     }
  353.  
  354.     bboxdiag=(bbox2-bbox1).length();
  355.     bboxC=(bbox1+bbox2)*0.5f;
  356. }
  357.  
  358. int flyEngine::collision_bsp(bsp_node *n,vector& p1,vector& p2,int elemtype,float rad)
  359. {
  360.     if (n->leaf!=-1)
  361.     {
  362.         bsp_object *e=n->elem;
  363.         vector rd=p2-p1;
  364.         float dist=1.0f,d;
  365.         mesh *m;
  366.         vector ip;
  367.         int f;
  368.         
  369.         hitobj=0;
  370.  
  371.         while(e)
  372.         {
  373.             if    (e!=flyengine->excludecollision && 
  374.                 (elemtype==0 || e->type==elemtype))
  375.             {
  376.                 m=e->ray_intersect(p1,rd,ip,d,f,rad);
  377.                 if (m && d<dist)
  378.                 {
  379.                     dist=d;
  380.                     hitobj=e;
  381.                     hitip=ip;
  382.                     hitface=f;
  383.                     hitmesh=m;
  384.                 }
  385.             }
  386.             e=e->next_elem;
  387.         }
  388.  
  389.         if (hitobj)
  390.             return 1;
  391.         else return 0;
  392.     }
  393.  
  394.     float d1=vec_dot(n->normal,p1)+n->d0, 
  395.         d2=vec_dot(n->normal,p2)+n->d0;
  396.     
  397.     if(d1<-rad && d2<-rad)
  398.         if (n->child[1])
  399.             return collision_bsp(n->child[1],p1,p2,elemtype,rad);
  400.         else return 0;
  401.     else 
  402.     if(d1>rad && d2>rad)
  403.         if (n->child[0])
  404.             return collision_bsp(n->child[0],p1,p2,elemtype,rad);
  405.         else return 0;
  406.     else 
  407.         {
  408.         if (d1>0)
  409.             {
  410.             if (n->child[0])
  411.                 if (collision_bsp(n->child[0],p1,p2,elemtype,rad))
  412.                     return 1;
  413.             if (n->child[1])
  414.                 if (collision_bsp(n->child[1],p1,p2,elemtype,rad))
  415.                     return 1;
  416.             }
  417.         else
  418.             {
  419.             if (n->child[1])
  420.                 if (collision_bsp(n->child[1],p1,p2,elemtype,rad))
  421.                     return 1;
  422.             if (n->child[0])
  423.                 if (collision_bsp(n->child[0],p1,p2,elemtype,rad))
  424.                     return 1;
  425.             }
  426.  
  427.         return 0;
  428.         }
  429. }
  430.  
  431. void flyEngine::compute_edges()
  432. {
  433.     if (edges)
  434.         delete edges;
  435.     edges=new int[nfaces*3*5];
  436.     if (faceedges)
  437.         delete faceedges;
  438.     faceedges=new int[nfaces*3];
  439.     nedges=0;
  440.     int i1,i2;
  441.     int i,j,nc,k;
  442.  
  443.     for( i=0;i<nfaces;i++ )
  444.         for( j=0;j<3;j++ )
  445.         {
  446.             i1=faces[i].vert[j]-vert;
  447.             i2=faces[i].vert[(j+1)%3]-vert;
  448.             nc=0;
  449.             for( k=0;k<nedges;k++,nc+=5 )
  450.                 if ((i1==edges[nc] && i2==edges[nc+1]) ||
  451.                     (i1==edges[nc+1] && i2==edges[nc]))
  452.                     break;
  453.             if (k==nedges)
  454.             {
  455.                 edges[nc]=i1;
  456.                 edges[nc+1]=i2;
  457.                 edges[nc+2]=i;
  458.                 edges[nc+3]=-1;
  459.                 edges[nc+4]=0;
  460.                 faceedges[i*3+j]=nedges;
  461.                 nedges++;
  462.             }
  463.             else 
  464.             {
  465.                 faceedges[i*3+j]=k;
  466.                 if ((faces[i].color-faces[edges[nc+2]].color).length()<0.1f)
  467.                     edges[nc+3]=i;
  468.             }
  469.         }
  470. }
  471.  
  472. void flyEngine::draw_bsp(int mode)
  473. {
  474.     nodedrawcount=0;
  475.     nelemdraw=0;
  476.     memset(nelemlatedraw,0,sizeof(int)*MAX_LATEDRAW_LAYERS);
  477.     nfacedraw=0;
  478.     nfacedrawtransp=0;
  479.     
  480.     draw_bsp(bsp);
  481.  
  482.     if (mode)
  483.     {
  484.         if (edges==0)
  485.             compute_edges();
  486.         draw_static_faces_cartoon(facedraw,nfacedraw);
  487.         draw_bsp_edges();
  488.     }
  489.     else
  490.     {
  491.         if (nfacedraw)
  492.             draw_static_faces(facedraw,nfacedraw);
  493.         if (nfacedrawtransp)
  494.             draw_static_faces(facedrawtransp,nfacedrawtransp);
  495.     }
  496.  
  497.     int i,j;
  498.     for( i=0;i<nelemdraw;i++ )
  499.         elemdraw[i]->draw();
  500.     for( j=0;j<MAX_LATEDRAW_LAYERS;j++ )
  501.         for( i=0;i<nelemlatedraw[j];i++ )
  502.             elemlatedraw[j][i]->draw();
  503. }
  504.  
  505. void flyEngine::draw_bsp(bsp_node *n)
  506. {
  507.     if (n->leaf!=-1)
  508.         {
  509.         if (cam->node==0 || (nodeonly && n!=cam->node))
  510.             return;
  511.         if (pvsoff || PVS_TEST(cam->node->leaf,n->leaf))
  512.             {
  513.             bsp_object *e=n->elem;
  514.             while(e)
  515.                 {
  516.                 if (e->type==TYPE_STATIC_MESH)
  517.                     {
  518.                     static_mesh *o=(static_mesh *)e;
  519.                     o->objmesh->lastdraw=cur_frame;
  520.                     for( int i=0;i<o->objmesh->nf;i++ )
  521.                         if (o->objmesh->faces[i]->lastdraw!=cur_frame)
  522.                         {
  523.                         if (FP_BITS(o->objmesh->faces[i]->color.w)==FP_ONE_BITS)
  524.                             facedraw[nfacedraw++]=o->objmesh->faces[i]->indx;
  525.                         else if (FP_BITS(o->objmesh->faces[i]->color.w)!=0)
  526.                             facedrawtransp[nfacedrawtransp++]=o->objmesh->faces[i]->indx;
  527.                         o->objmesh->faces[i]->lastdraw=cur_frame;
  528.                         }
  529.                     }
  530.                 else 
  531.                     elemlatedraw[e->latedraw&7][nelemlatedraw[e->latedraw&7]++]=e;
  532.                 e=e->next_elem;
  533.                 }
  534.             nodedrawcount++;
  535.             }
  536.         return;
  537.         }
  538.  
  539.     float x1,x2;
  540.     int i;
  541.  
  542.     x1=n->distance(frustrum[0]);
  543.     for( i=1;i<5;i++ )
  544.         {
  545.         x2=n->distance(frustrum[i]);
  546.         if (x1*x2<=0)
  547.             break;
  548.         }
  549.     if (i==5)
  550.         if (x1>0)
  551.         {
  552.             if (n->child[0]) 
  553.                 draw_bsp(n->child[0]);
  554.         }
  555.         else 
  556.         { 
  557.             if (n->child[1]) 
  558.                 draw_bsp(n->child[1]);
  559.         }
  560.     else 
  561.         if (x1<0)
  562.             {
  563.             if (n->child[1]) 
  564.                 draw_bsp(n->child[1]);
  565.             if (n->child[0]) 
  566.                 draw_bsp(n->child[0]);
  567.             }
  568.         else 
  569.             {
  570.             if (n->child[0]) 
  571.                 draw_bsp(n->child[0]);
  572.             if (n->child[1]) 
  573.                 draw_bsp(n->child[1]);
  574.             }
  575. }
  576.  
  577. int flyEngine::step()
  578. {        
  579.     static int dt,t0=timeGetTime()-start_time;
  580.  
  581.     // compute elapsed time
  582.     cur_time=timeGetTime()-start_time;
  583.     dt=cur_time-t0;
  584.     if (dt>0)
  585.         {
  586.         t0=cur_time;
  587.         if (dt<1000)
  588.             {
  589.             step(dt);
  590.             return dt;
  591.             }
  592.         }
  593.     return 0;
  594. }
  595.  
  596. void flyEngine::step(int dt)
  597. {
  598.     if (flyengine->player==0 || flyengine->cam==0 || flyengine->bsp==0)
  599.         return;
  600.  
  601.     // process console commands
  602.     if (flyengine->console_command[0])
  603.         {
  604.         char *c=flyengine->console_command;
  605.         do
  606.             {
  607.             flyengine->con.command_exec(c);
  608.             c=strchr(c,';');
  609.             if (c)
  610.                 *(c++)=0;
  611.             } 
  612.         while(c);
  613.         }
  614.     flyengine->console_command[0]=0;
  615.  
  616.     int i;
  617.     // if not in server mode
  618.     if (directx->mpmode!=FLYMP_SERVER)
  619.     {
  620.     // get input
  621.     if (noinput)
  622.         {
  623.         memset(directx->diks,0,sizeof(directx->diks));
  624.         memset(&directx->dims,0,sizeof(directx->dims));
  625.         }
  626.     else directx->get_input();
  627.  
  628.     // attebuate filter
  629.     if (FP_BITS(filter.x)!=0)
  630.         {
  631.         filter.x-=dt/500.0f;
  632.         if (FP_SIGN_BIT(filter.x)) filter.x=0;
  633.         }
  634.     if (FP_BITS(filter.y)!=0)
  635.         {
  636.         filter.y-=dt/500.0f;
  637.         if (FP_SIGN_BIT(filter.y)) filter.y=0;
  638.         }
  639.     if (FP_BITS(filter.z)!=0)
  640.         {
  641.         filter.z-=dt/500.0f;
  642.         if (FP_SIGN_BIT(filter.z)) filter.z=0;
  643.         }
  644.  
  645.     // if a texture cache available
  646.     if (tc)
  647.     for( i=0;i<nlm;i++ )
  648.         {
  649.         // update changed lightmaps
  650.         if (lm[i]->lastupdate)
  651.             {
  652.             lm[i]->load(lmpic[lm[i]->pic]);
  653.             lm[i]->lastupdate=-1;
  654.             }
  655.         // update changed fogmaps
  656.         if (fm[i]->lastupdate)
  657.             {
  658.             memset(fm[i]->bmp,0,fm[i]->bytesxy);
  659.             fm[i]->lastupdate=-1;
  660.             }
  661.         }
  662.     }
  663.  
  664.     bsp_object *o=active_obj0,*op=0;
  665.     cur_step_base=cur_step+1;
  666.     cur_dt=dt;
  667.  
  668.     // loop all active objects
  669.     while(o)
  670.         {
  671.         stepobj=o;
  672.  
  673.         // if object life is negative, destroy it
  674.         if (o->life<0)
  675.             {
  676.             if (last_active_obj==o)
  677.                 last_active_obj=op;
  678.             bsp_object *n=(bsp_object *)o->next_obj;
  679.             delete o;
  680.             if (op==0)
  681.                 active_obj0=n;
  682.             else op->next_obj=n;
  683.             o=n;
  684.             continue;
  685.             }
  686.         else
  687.             {
  688.             // step object and reposition in bsp if needed
  689.             cur_step++;
  690.             if (o->step(dt))
  691.                 if (o->node)
  692.                     {
  693.                     o->remove_from_bsp();
  694.                     o->add_to_bsp();
  695.                     }
  696.             }
  697.         op=o;
  698.         o=(bsp_object *)o->next_obj;
  699.         }
  700.     stepobj=0;
  701.  
  702.     // if a texture cache is available and not in server mode
  703.     if (tc && directx->mpmode!=FLYMP_SERVER)
  704.     {
  705.     for( i=0;i<nlm;i++ )
  706.         {
  707.         // update changed lightmap
  708.         if (lm[i]->lastupdate)
  709.             {
  710.             if (lm[i]->lastupdate==-1)
  711.                 lm[i]->lastupdate=0;
  712.             tc->update_sub_picture(
  713.                 lm[i]->pic+lmbase,lm[i]->offsetx,lm[i]->offsety,
  714.                 lm[i]->sizex,lm[i]->sizey,3,lm[i]->bmp);
  715.             }
  716.         // update changed fogmap
  717.         if (fm[i]->lastupdate)
  718.             {
  719.             if (fm[i]->lastupdate==-1)
  720.                 fm[i]->lastupdate=0;
  721.             tc->update_sub_picture(
  722.                 fm[i]->pic+fmbase,fm[i]->offsetx,fm[i]->offsety,
  723.                 fm[i]->sizex,fm[i]->sizey,4,fm[i]->bmp);
  724.             }
  725.         }
  726.     }
  727.  
  728.     // step all running plugins
  729.     dll.send_message(FLYM_UPDATESCENE,dt,0);
  730.  
  731.     // if in multiplayer, check multiplayer messages
  732.     if (directx->mpmode!=FLYMP_NOMP)
  733.         check_multiplayer();
  734.  
  735.     // if in client multiplayer mode
  736.     if (directx->mpmode==FLYMP_CLIENT)
  737.         {
  738.         // update client objects to server at slower intervals
  739.         static int last_mp_update=0;
  740.         if (cur_time-last_mp_update>mpdelay)
  741.             {
  742.             last_mp_update=flyengine->cur_time;
  743.             dll.send_message(FLYM_MPUPDATE,0,0);
  744.             }
  745.         }
  746.  
  747.     // step console
  748.     if (con.mode)
  749.         con.step(dt);
  750. }
  751.  
  752. void flyEngine::apply_bsp(bsp_node *n,vector& p,float rad,void *data,void (*func)(void *data,bsp_object *e))
  753. {
  754.     if (n->leaf!=-1)
  755.         {
  756.         if (n->elem)
  757.             {
  758.             bsp_object *e=n->elem;
  759.             rad*=rad;
  760.             vector v;
  761.             if (e->type==TYPE_STATIC_MESH)
  762.                 {
  763.                 func(data,e);
  764.                 e=e->next_elem;
  765.                 }
  766.             while(e)
  767.                 {
  768.                 v.x=e->pos.x-p.x;
  769.                 v.y=e->pos.y-p.y;
  770.                 v.z=e->pos.z-p.z;
  771.                 if (v.x*v.x+v.y*v.y+v.z*v.z<rad)
  772.                     func(data,e);
  773.                 e=e->next_elem;
  774.                 }
  775.             }
  776.         return;
  777.         }
  778.  
  779.     float d=n->distance(p);
  780.  
  781.     if (fabs(d)<rad)
  782.         {
  783.         if (n->child[0])
  784.             apply_bsp(n->child[0],p,rad,data,func);
  785.         if (n->child[1])
  786.             apply_bsp(n->child[1],p,rad,data,func);
  787.         }
  788.     else 
  789.         if (d>0)
  790.             {
  791.             if (n->child[0])
  792.                 apply_bsp(n->child[0],p,rad,data,func);
  793.             }
  794.         else 
  795.             if (n->child[1])
  796.                 apply_bsp(n->child[1],p,rad,data,func);
  797. }
  798.  
  799. void flyEngine::apply_bsp(bsp_node *n,vector *p,int np,void *data,void (*func)(void *data,bsp_object *e))
  800. {
  801.     if (n->leaf!=-1)
  802.         {
  803.         bsp_object *e=n->elem;
  804.         while(e)
  805.             {
  806.             func(data,e);
  807.             e=e->next_elem;
  808.             }
  809.         return;
  810.         }
  811.  
  812.     float x1,x2;
  813.     int i;
  814.  
  815.     x1=n->distance(p[0]);
  816.     for( i=1;i<np;i++ )
  817.         {
  818.             x2=n->distance(p[i]);
  819.             if (x1*x2<=0)
  820.                 break;
  821.         }
  822.     if (i==5)
  823.         if (x1>0)
  824.         {
  825.             if (n->child[0])
  826.                 apply_bsp(n->child[0],p,np,data,func);
  827.         }
  828.         else 
  829.         {
  830.             if (n->child[1])
  831.                 apply_bsp(n->child[1],p,np,data,func);
  832.         }
  833.     else 
  834.     {
  835.         if (n->child[0])
  836.             apply_bsp(n->child[0],p,np,data,func);
  837.         if (n->child[1])
  838.             apply_bsp(n->child[1],p,np,data,func);
  839.     }
  840. }
  841.  
  842. void flyEngine::send_bsp_message(bsp_node *n,vector& p,float rad,int msg,int param,void *data)
  843. {
  844.     static float d;
  845.  
  846.     if (n->leaf!=-1)
  847.         {
  848.         bsp_object *e=n->elem;
  849.         while(e)
  850.             {
  851.             e->message(p,rad,msg,param,data);
  852.             e=e->next_elem;
  853.             }
  854.         return;
  855.         }
  856.  
  857.     d=n->distance(p);
  858.  
  859.     if (fabs(d)<rad)
  860.         {
  861.         if (n->child[0])
  862.             send_bsp_message(n->child[0],p,rad,msg,param,data);
  863.         if (n->child[1])
  864.             send_bsp_message(n->child[1],p,rad,msg,param,data);
  865.         }
  866.     else 
  867.         if (d>0)
  868.             if (n->child[0])
  869.                 send_bsp_message(n->child[0],p,rad,msg,param,data);
  870.             else ;
  871.         else
  872.             if (n->child[1])
  873.                 send_bsp_message(n->child[1],p,rad,msg,param,data);
  874. }
  875.  
  876. int flyEngine::collision_test(bsp_node *n,vector& p1,vector& p2,int elemtype,float rad)
  877. {
  878.     if (n->leaf!=-1)
  879.         {
  880.         bsp_object *e=n->elem;
  881.         while(e)
  882.             {
  883.             if    (e!=excludecollision && 
  884.                 (elemtype==0 || e->type==elemtype))
  885.                 if (e->ray_intersect_test(p1,p2-p1,rad))
  886.                     return 1;
  887.             e=e->next_elem;
  888.             }
  889.         return 0;
  890.         }
  891.  
  892.     float d1=vec_dot(n->normal,p1)+n->d0, 
  893.         d2=vec_dot(n->normal,p2)+n->d0;
  894.  
  895.     if(d1<SMALL && d2<SMALL)
  896.         if (n->child[1])
  897.             return collision_test(n->child[1],p1,p2,elemtype,rad);
  898.         else return 0;
  899.     else if(d1>SMALL && d2>SMALL)
  900.         if (n->child[0])
  901.             return collision_test(n->child[0],p1,p2,elemtype,rad);
  902.         else return 0;
  903.     else 
  904.         {
  905.         if (n->child[0])
  906.             if (collision_test(n->child[0],p1,p2,elemtype,rad))
  907.                 return 1;
  908.         if (n->child[1])
  909.             if (collision_test(n->child[1],p1,p2,elemtype,rad))
  910.                 return 1;
  911.  
  912.         return 0;
  913.         }
  914. }
  915.  
  916. void flyEngine::find_leaf(bsp_node *n)
  917. {
  918.     if (n->child[0]==0 && n->child[1]==0)
  919.         {
  920.         if (n->leaf!=-1)
  921.             if (leaf)
  922.                 leaf[n->leaf]=n;
  923.             else nleaf++;
  924.         return;
  925.         }
  926.     n->leaf=-1;
  927.     if (n->child[0])
  928.         find_leaf(n->child[0]);
  929.     if (n->child[1])
  930.         find_leaf(n->child[1]);
  931. }
  932.  
  933. void flyEngine::alloc_pvs(char value)
  934. {
  935.     if (pvs)
  936.         delete pvs;
  937.     pvs=0;
  938.     pvssize=0;
  939.     pvsrowsize=0;
  940.     if (leaf)
  941.         delete leaf;
  942.     leaf=0;
  943.     nleaf=0;
  944.  
  945.     if (bsp)
  946.     {
  947.         find_leaf(bsp);
  948.         if (nleaf==0)
  949.             return;
  950.         leaf=new bsp_node *[nleaf];
  951.         memset(leaf,0,nleaf*sizeof(bsp_node *));
  952.         find_leaf(bsp);
  953.     }
  954.  
  955.     if (nleaf)
  956.         {
  957.         pvsrowsize=nleaf/8+1;
  958.         if (pvsrowsize&3)
  959.             pvsrowsize+=4-(pvsrowsize&3);
  960.         pvssize=pvsrowsize*nleaf;
  961.         pvs=new char[pvssize];
  962.         memset(pvs,value,pvssize);
  963.         }
  964. }
  965.  
  966. bsp_node *flyEngine::find_node(bsp_node *n,vector& v,float mindist)
  967. {
  968.     float dist;
  969.     while(n->child[0]!=0 || n->child[1]!=0)
  970.     {
  971.     dist=n->distance(v);
  972.     if (fabs(dist)<mindist)
  973.         return 0;
  974.     if (dist>=0)
  975.         if (n->child[0])
  976.             n=n->child[0];
  977.         else return 0;
  978.     else if (n->child[1])
  979.             n=n->child[1];
  980.         else return 0;
  981.     }
  982.     return n;
  983. }
  984.  
  985. bsp_node *flyEngine::get_random_point(vector& v,float mindist)
  986. {
  987.     if (bsp==0)
  988.     {
  989.         v.null();
  990.         return 0;
  991.     }
  992.  
  993.     vector diag=bbox2-bbox1;
  994.     bsp_node *n;
  995.     int maxpoints=100;
  996.  
  997.     new_point:
  998.         if (--maxpoints==0)
  999.         {
  1000.             v.null();
  1001.             return 0;
  1002.         }
  1003.         v.x=bbox1.x+FABSRAND*diag.x;
  1004.         v.y=bbox1.y+FABSRAND*diag.y;
  1005.         v.z=bbox1.z+FABSRAND*diag.z;
  1006.         n=find_node(bsp, v, mindist);
  1007.         if (n==0 || n->leaf==-1)
  1008.             goto new_point;
  1009.         return n;
  1010. }
  1011.  
  1012. void flyEngine::set_status_msg(char *fmt, ...)
  1013. {
  1014.     char ach[128];
  1015.     va_list va;
  1016.     va_start( va, fmt );
  1017.     wvsprintf( ach, fmt, va );
  1018.     va_end( va );
  1019.  
  1020.     strcpy(status_msg,ach);
  1021.     status_msg_time=cur_time;
  1022.  
  1023.     con.add_string(ach);
  1024. }
  1025.  
  1026. void flyEngine::activate(bsp_object *d,int flag)
  1027. {
  1028.     if (bsp==0 || d==0) 
  1029.         return;
  1030.     
  1031.     d->next_obj=0;
  1032.     if (last_active_obj)
  1033.         last_active_obj->next_obj=d;
  1034.     else
  1035.         active_obj0=d;
  1036.     last_active_obj=d;
  1037.  
  1038.     d->node=0;
  1039.     if (flag)
  1040.         d->add_to_bsp();
  1041. }
  1042.  
  1043. int flyEngine::open_fly_file(char *file)
  1044. {
  1045.     char str[256];
  1046.     
  1047.     close_fly_file();
  1048.  
  1049.     strcpy(str,file);
  1050.     strlwr(str);
  1051.  
  1052.     strcpy(flyfile,str);
  1053.  
  1054.     strcpy(flydatapath,flysdkpath);
  1055.     strcat(flydatapath,"data\\");
  1056.  
  1057.     strcpy(flyfilename,flydatapath);
  1058.     strcat(flyfilename,flyfile);
  1059.  
  1060.     char *c=strrchr(str,'\\');
  1061.     if (c==0) c=strrchr(str,'/');
  1062.     if (c) { *(c+1)=0; strcat(flydatapath,str); }
  1063.  
  1064.     if (load_data()==0)
  1065.     {
  1066.         reset();
  1067.         return 0;
  1068.     }
  1069.  
  1070.     init_texture_cache();
  1071.  
  1072.     return 1;
  1073. }
  1074.  
  1075. int flyEngine::save_fly_file(char *file)
  1076. {
  1077.     strlwr(file);
  1078.     strcpy(flyfile,file);
  1079.     strcpy(flydatapath,flysdkpath);
  1080.     strcat(flydatapath,"data\\");
  1081.     strcpy(flyfilename,flydatapath);
  1082.     strcat(flyfilename,flyfile);
  1083.     char *c=strrchr(file,'\\');
  1084.     if (c==0) c=strrchr(file,'/');
  1085.     if (c) { *(c+1)=0; strcat(flydatapath,file); }
  1086.     FILE *fp=fopen(flyfilename,"wt");
  1087.     if (fp==0) 
  1088.     {
  1089.         flydatapath[0]=0;
  1090.         flyfilename[0]=0;
  1091.         flyfile[0]=0;
  1092.         return 0;
  1093.     }
  1094.     
  1095.     char *name;
  1096.     int i,j,n,type;
  1097.     bsp_object *o;
  1098.     param_desc pd;
  1099.  
  1100.     fprintf(fp,"[classes]\n");
  1101.     for( i=0;i<dll.ndll;i++ )
  1102.         fprintf(fp,"dll%i=%s\n",i,dll.dll[i]->dll_filename);
  1103.  
  1104.     for( i=0;i<dll.ncd;i++ )
  1105.         {
  1106.         name=dll.cd[i]->get_name();
  1107.         type=dll.cd[i]->get_type();
  1108.         o=stock_obj0;
  1109.         n=0;
  1110.         while(o)
  1111.             {
  1112.             if (o->type==type)
  1113.                 sprintf(o->name,"%s%i",name,n++);
  1114.             o=(bsp_object *)o->next_obj;
  1115.             }
  1116.         }
  1117.     o=active_obj0;
  1118.     while(o)
  1119.         {
  1120.         if (o->source)
  1121.             strcpy(o->name,o->source->name);
  1122.         o=(bsp_object *)o->next_obj;
  1123.         }
  1124.  
  1125.     for( i=0;i<dll.ncd;i++ )
  1126.         {
  1127.         name=dll.cd[i]->get_name();
  1128.         type=dll.cd[i]->get_type();
  1129.         o=stock_obj0;
  1130.         n=0;
  1131.         while(o)
  1132.             {
  1133.             if (o->type==type)
  1134.                 {
  1135.                 fprintf(fp,"\n");
  1136.                 fprintf(fp,"[%s]\nlongname=%s\n",o->name,o->long_name);
  1137.                 n=o->get_param_desc(0,0);
  1138.                 for( j=0;j<n;j++ )
  1139.                     {
  1140.                     o->get_param_desc(j,&pd);
  1141.                     fprintf(fp,"%s=%s\n",pd.name,pd.get_string());
  1142.                     }
  1143.                 }
  1144.             o=(bsp_object *)o->next_obj;
  1145.             }
  1146.         }
  1147.  
  1148.     fprintf(fp,"\n");
  1149.     fprintf(fp,"[fly]\n");
  1150.     n=get_global_param_desc(0,0);
  1151.     for( i=0;i<n;i++ )
  1152.         {
  1153.         get_global_param_desc(i,&pd);
  1154.         if (pd.type!=' ')
  1155.             fprintf(fp,"%s=%s\n",pd.name,pd.get_string());
  1156.         }
  1157.  
  1158.     fclose(fp);
  1159.     return 1;
  1160. }
  1161.  
  1162. void flyEngine::close_fly_file()
  1163. {
  1164.     dll.send_message(FLYM_CLOSESCENE,0,0);
  1165.     close_texture_cache();
  1166.     reset();
  1167. }
  1168.  
  1169. void flyEngine::init_texture_cache()
  1170. {
  1171.     if (rend==0)
  1172.         return;
  1173.  
  1174.     if (tc) delete tc;
  1175.     tc=new textcacheGL();
  1176.     tc->init(npiclib,piclib);
  1177.     
  1178.     int i;
  1179.     lmbase=tc->npic;
  1180.     for( i=0;i<nlmpic;i++ )
  1181.         tc->add_picture(lmpic[i]->sizex,lmpic[i]->sizey,3,lmpic[i]->bmp);
  1182.     fmbase=tc->npic;
  1183.     for( i=0;i<nlmpic;i++ )
  1184.         tc->add_picture(fmpic[i]->sizex,fmpic[i]->sizey,4,fmpic[i]->bmp);
  1185. }
  1186.  
  1187. void flyEngine::close_texture_cache()
  1188. {
  1189.     if (tc) delete tc;
  1190.     tc=0;
  1191. }
  1192.  
  1193. void flyEngine::set_camera(bsp_object *d)
  1194. {
  1195.     cam=d;
  1196.     float disty=viewmaxdist*(float)tan(camangle*0.5f*PiOver180);
  1197.     float distx=disty*aspect;
  1198.     if (cam)
  1199.         {
  1200.         frustrum[0]=cam->pos;
  1201.         
  1202.         frustrum[1].x = cam->pos.x - viewmaxdist*cam->Z.x +
  1203.                     distx*cam->X.x + disty*cam->Y.x;
  1204.         frustrum[1].y = cam->pos.y - viewmaxdist*cam->Z.y +
  1205.                     distx*cam->X.y + disty*cam->Y.y;
  1206.         frustrum[1].z = cam->pos.z - viewmaxdist*cam->Z.z +
  1207.                     distx*cam->X.z + disty*cam->Y.z;
  1208.  
  1209.         frustrum[2].x = cam->pos.x - viewmaxdist*cam->Z.x +
  1210.                     distx*cam->X.x - disty*cam->Y.x;
  1211.         frustrum[2].y = cam->pos.y - viewmaxdist*cam->Z.y +
  1212.                     distx*cam->X.y - disty*cam->Y.y;
  1213.         frustrum[2].z = cam->pos.z - viewmaxdist*cam->Z.z +
  1214.                     distx*cam->X.z - disty*cam->Y.z;
  1215.  
  1216.         frustrum[3].x = cam->pos.x - viewmaxdist*cam->Z.x -
  1217.                     distx*cam->X.x - disty*cam->Y.x;
  1218.         frustrum[3].y = cam->pos.y - viewmaxdist*cam->Z.y -
  1219.                     distx*cam->X.y - disty*cam->Y.y;
  1220.         frustrum[3].z = cam->pos.z - viewmaxdist*cam->Z.z -
  1221.                     distx*cam->X.z - disty*cam->Y.z;
  1222.  
  1223.         frustrum[4].x = cam->pos.x - viewmaxdist*cam->Z.x -
  1224.                     distx*cam->X.x + disty*cam->Y.x;
  1225.         frustrum[4].y = cam->pos.y - viewmaxdist*cam->Z.y -
  1226.                     distx*cam->X.y + disty*cam->Y.y;
  1227.         frustrum[4].z = cam->pos.z - viewmaxdist*cam->Z.z -
  1228.                     distx*cam->X.z + disty*cam->Y.z;
  1229.  
  1230.         glMatrixMode( GL_PROJECTION );
  1231.         glLoadIdentity();
  1232.         gluPerspective( flyengine->camangle, flyengine->aspect, flyengine->viewmindist,flyengine->viewmaxdist*1.5f);
  1233.         glMatrixMode( GL_MODELVIEW );
  1234.         glLoadIdentity();
  1235.         glMultMatrixf((float *)&cam->mat_t);
  1236.         glTranslatef(-cam->pos.x,-cam->pos.y,-cam->pos.z);
  1237.         }
  1238. }
  1239.  
  1240. int flyEngine::get_picture(char *file)
  1241. {
  1242.     if (file[0]==0)
  1243.         return -1;
  1244.  
  1245.     int j;
  1246.     for( j=0;j<npiclib;j++ )
  1247.         if (!stricmp(piclib[j]->name,file))
  1248.             break;
  1249.  
  1250.     if (j==npiclib)
  1251.         {
  1252.         picture *p=new picture;
  1253.         char name[256];
  1254.         strcpy(name,flydatapath);
  1255.         strcat(name,"maps\\");
  1256.         strcat(name,file);
  1257.         if (p->LoadPIC(name))
  1258.             {
  1259.             piclib[npiclib]=p;
  1260.             strcpy(piclib[npiclib]->name,file);
  1261.             return npiclib++;
  1262.             }
  1263.         else
  1264.             {
  1265.             delete p;
  1266.             return -1;
  1267.             }
  1268.         }
  1269.  
  1270.     return j;
  1271. }
  1272.  
  1273. int flyEngine::load_pictures(char *namef)
  1274. {
  1275.     fly_pak fp;
  1276.     int i,n;
  1277.     char name[256],str[256];
  1278.  
  1279.     if(!fp.open(namef))
  1280.         return 0;
  1281.  
  1282.     n=fp.get_int();
  1283.     fp.get_string(str);
  1284.     for(i=0;i<n;i++)
  1285.         {
  1286.         fp.get_string(str);
  1287.         piclib[i]=new picture;
  1288.         strcpy(name,flydatapath);
  1289.         strcat(name,"maps\\");
  1290.         strcat(name,str);
  1291.         piclib[npiclib+i]->LoadPIC(name);
  1292.         strcpy(piclib[npiclib+i]->name,str);
  1293.         }
  1294.     npiclib+=n;
  1295.  
  1296.     return 1;
  1297. }
  1298.  
  1299. int flyEngine::load_bsp(char *file) 
  1300. {
  1301.     unsigned char uc;
  1302.     int w[3];
  1303.     int i,nv;
  1304.  
  1305.     fly_pak fp;
  1306.  
  1307.     if (!fp.open(file))
  1308.         return 0;
  1309.  
  1310.     fp.read(&nv,sizeof(int));
  1311.     nvert=abs(nv);
  1312.     
  1313.     vert=new vector[nvert];
  1314.  
  1315.     for( i=0;i<nvert;i++ )
  1316.         fp.read(&vert[i],3*sizeof(float));
  1317.     if (nv<0)
  1318.     {
  1319.     vertcolor=new vector[nvert];
  1320.     for( i=0;i<nvert;i++ )
  1321.         {
  1322.         fp.read(&uc,1);
  1323.         vertcolor[i].x=uc/255.0f;
  1324.         fp.read(&uc,1);
  1325.         vertcolor[i].y=uc/255.0f;
  1326.         fp.read(&uc,1);
  1327.         vertcolor[i].z=uc/255.0f;
  1328.         fp.read(&uc,1);
  1329.         vertcolor[i].w=1.0f;
  1330.         }
  1331.     }
  1332.  
  1333.     fp.read(&nfaces,sizeof(int));
  1334.     faces=new face[nfaces];
  1335.     facedraw=new int[nfaces];
  1336.     facedrawtransp=new int[nfaces];
  1337.     for( i=0;i<nfaces;i++ )
  1338.         {
  1339.         fp.read(w,sizeof(int)*3);
  1340.         faces[i].vert[0]=&vert[w[0]];
  1341.         faces[i].vert[1]=&vert[w[1]];
  1342.         faces[i].vert[2]=&vert[w[2]];
  1343.         fp.read(&faces[i].texpic,sizeof(int));
  1344.         fp.read(&faces[i].emmradius,sizeof(float));
  1345.         fp.read(faces[i].uv,sizeof(float)*6);
  1346.         fp.read(&uc,1);
  1347.         faces[i].color.x=uc/255.0f;
  1348.         fp.read(&uc,1);
  1349.         faces[i].color.y=uc/255.0f;
  1350.         fp.read(&uc,1);
  1351.         faces[i].color.z=uc/255.0f;
  1352.         fp.read(&uc,1);
  1353.         faces[i].color.w=uc/255.0f;
  1354.         faces[i].indx=i;
  1355.         }
  1356.  
  1357.     load_bsp(&bsp,&fp);
  1358.     fp.close();
  1359.  
  1360.     compute_normals();
  1361.  
  1362.     return 1;
  1363. }
  1364.  
  1365. void flyEngine::load_bsp(bsp_node **n,fly_pak *fp)
  1366. {
  1367.     char c;
  1368.     int f,i;
  1369.     int w;
  1370.  
  1371.     fp->read(&c,1);
  1372.     if (c==0)
  1373.         return;
  1374.  
  1375.     *n=new bsp_node;
  1376.  
  1377.     fp->read(&(*n)->leaf,sizeof(int));
  1378.  
  1379.     fp->read(&(*n)->normal,3*sizeof(float));
  1380.     fp->read(&(*n)->d0,sizeof(float));
  1381.  
  1382.     fp->read(&f,sizeof(int));
  1383.     if (f)
  1384.         {
  1385.         static_mesh *so=new static_mesh;
  1386.         so->objmesh->pivotpos.null();
  1387.         so->objmesh->nf=f;
  1388.         so->objmesh->faces=new face *[so->objmesh->nf];
  1389.         for( i=0;i<so->objmesh->nf;i++ )
  1390.             {
  1391.             fp->read(&w,sizeof(int));
  1392.             so->objmesh->faces[i]=&faces[w];
  1393.             so->objmesh->faces[i]->lastdraw=0;
  1394.             }
  1395.         so->objmesh->compute_normals(MESH_FACENORM|MESH_VERTNORM|MESH_BBOX);
  1396.         so->next_elem=(*n)->elem;
  1397.         (*n)->elem=so;
  1398.         (*n)->last_elem=&so->next_elem;
  1399.         }
  1400.  
  1401.     load_bsp(&(*n)->child[0],fp);
  1402.     load_bsp(&(*n)->child[1],fp);
  1403. }
  1404.  
  1405. void flyEngine::save_bsp(bsp_node *n,FILE *fp)
  1406. {
  1407.     char c;
  1408.     int i;
  1409.     int w;
  1410.  
  1411.     if (n==0)
  1412.         {
  1413.         c=0;
  1414.         fwrite(&c,1,1,fp);
  1415.         return;
  1416.         }
  1417.  
  1418.     c=1;
  1419.     fwrite(&c,1,1,fp);
  1420.  
  1421.     fwrite(&n->leaf,1,sizeof(int),fp);
  1422.  
  1423.     fwrite(&n->normal, 3, sizeof(float), fp);
  1424.     fwrite(&n->d0, 1, sizeof(float), fp);
  1425.  
  1426.     bsp_object *e=n->elem;
  1427.     while(e)
  1428.         {
  1429.         if (e->type==TYPE_STATIC_MESH)
  1430.             break;
  1431.         e=e->next_elem;
  1432.         }
  1433.     static_mesh *so=(static_mesh *)e;
  1434.     if (so)
  1435.         {
  1436.         fwrite(&so->objmesh->nf,1,sizeof(int),fp);
  1437.         for( i=0;i<so->objmesh->nf;i++ )
  1438.             {
  1439.             w=so->objmesh->faces[i]->indx;
  1440.             fwrite(&w,1,sizeof(int),fp);
  1441.             }
  1442.         }
  1443.     else 
  1444.         {
  1445.         i=0;
  1446.         fwrite(&i,1,sizeof(int),fp);
  1447.         }
  1448.  
  1449.     save_bsp(n->child[0],fp);
  1450.     save_bsp(n->child[1],fp);
  1451. }
  1452.  
  1453. int flyEngine::save_bsp(char *file)
  1454. {
  1455.     if (bsp==0)
  1456.         return 0;
  1457.  
  1458.     FILE *fp;
  1459.     unsigned char uc;
  1460.     int w[3];
  1461.     int i,nv;
  1462.  
  1463.     fp=fopen(file,"wb");
  1464.     if (!fp)
  1465.         return 0;
  1466.  
  1467.     if (vertcolor)
  1468.         nv=-nvert;
  1469.     else nv=nvert;
  1470.  
  1471.     fwrite(&nv,1,sizeof(int),fp);
  1472.  
  1473.     for( i=0;i<nvert;i++ )
  1474.         fwrite(&vert[i],3,sizeof(float),fp);
  1475.     if (nv<0)
  1476.     for( i=0;i<nvert;i++ )
  1477.     {
  1478.         uc=(unsigned char)(vertcolor[i].x*255);
  1479.         fwrite(&uc,1,1,fp);
  1480.         uc=(unsigned char)(vertcolor[i].y*255);
  1481.         fwrite(&uc,1,1,fp);
  1482.         uc=(unsigned char)(vertcolor[i].z*255);
  1483.         fwrite(&uc,1,1,fp);
  1484.         uc=255;
  1485.         fwrite(&uc,1,1,fp);
  1486.     }
  1487.  
  1488.     fwrite(&nfaces,1,sizeof(int),fp);
  1489.     for( i=0;i<nfaces;i++ )
  1490.         {
  1491.         faces[i].indx=i;
  1492.  
  1493.         w[0]=(int)(faces[i].vert[0]-vert);
  1494.         w[1]=(int)(faces[i].vert[1]-vert);
  1495.         w[2]=(int)(faces[i].vert[2]-vert);
  1496.         fwrite(w,sizeof(int),3,fp);
  1497.         fwrite(&faces[i].texpic,sizeof(int),1,fp);
  1498.         fwrite(&faces[i].emmradius,sizeof(float),1,fp);
  1499.         
  1500.         fwrite(faces[i].uv,sizeof(float),6,fp);
  1501.  
  1502.         uc=(unsigned char)(faces[i].color.x*255);
  1503.         fwrite(&uc,1,1,fp);
  1504.         uc=(unsigned char)(faces[i].color.y*255);
  1505.         fwrite(&uc,1,1,fp);
  1506.         uc=(unsigned char)(faces[i].color.z*255);
  1507.         fwrite(&uc,1,1,fp);
  1508.         uc=(unsigned char)(faces[i].color.w*255);
  1509.         fwrite(&uc,1,1,fp);
  1510.         }
  1511.  
  1512.     save_bsp(bsp,fp);
  1513.  
  1514.     fclose(fp);
  1515.  
  1516.     return 1;
  1517. }
  1518.  
  1519. int flyEngine::load_lightmaps(char *file)
  1520. {
  1521.     if (nfaces==0)
  1522.         return 0;
  1523.     int i,x,y,sx,sy,f,p;
  1524.     fly_pak fp;
  1525.     
  1526.     if (!fp.open(file)) return 0;
  1527.  
  1528.     fp.read(&i,sizeof(int));
  1529.     if (i!=nfaces) 
  1530.     { fp.close(); return 0;};
  1531.     
  1532.     for( i=0;i<nfaces;i++ )
  1533.         {
  1534.         fp.read(&faces[i].lm,sizeof(int));
  1535.         fp.read(&faces[i].lmuv,sizeof(float)*6);
  1536.         }
  1537.  
  1538.     fp.read(&nlmpic,sizeof(int));
  1539.     for( i=0;i<nlmpic;i++ )
  1540.         {
  1541.         fp.read(&sx,sizeof(int));
  1542.         fp.read(&sy,sizeof(int));
  1543.         lmpic[i]=new light_map_pic(sx,sy);
  1544.         fp.read(lmpic[i]->bmp,lmpic[i]->bytesxy);
  1545.         }
  1546.  
  1547.     fp.read(&nlm,sizeof(int));
  1548.     for( i=0;i<nlm;i++ )
  1549.     {
  1550.         fp.read(&f,sizeof(int));
  1551.         fp.read(&p,sizeof(int));
  1552.         fp.read(&x,sizeof(int));
  1553.         fp.read(&y,sizeof(int));
  1554.         fp.read(&sx,sizeof(int));
  1555.         fp.read(&sy,sizeof(int));
  1556.         lm[i]=new light_map(f,p,x,y,sx,sy,3);
  1557.         lm[i]->load(lmpic[p]);
  1558.     }
  1559.  
  1560.     fp.close();
  1561.  
  1562.     for( i=0;i<nlmpic;i++ )
  1563.     {
  1564.         fmpic[i]=new light_map_pic(lmpic[i]->sizex,lmpic[i]->sizey,4);
  1565.         memset(fmpic[i]->bmp,0,fmpic[i]->bytesxy);
  1566.     }
  1567.     for( i=0;i<nlm;i++ )
  1568.     {
  1569.         fm[i]=new light_map(lm[i]->facenum,lm[i]->pic,lm[i]->offsetx,lm[i]->offsety,lm[i]->sizex,lm[i]->sizey,4);
  1570.         memset(fm[i]->bmp,0,fm[i]->bytesxy);
  1571.         if (lm[i]->facenum!=-1)
  1572.             lm[i]->set_base(&faces[lm[i]->facenum],lmpic[lm[i]->pic]);
  1573.         if (fm[i]->facenum!=-1)
  1574.             fm[i]->set_base(&faces[fm[i]->facenum],fmpic[fm[i]->pic]);
  1575.     }
  1576.  
  1577.     return 1;
  1578. }
  1579. int flyEngine::save_lightmaps(char *file)
  1580. {
  1581.     if (nfaces==0)
  1582.         return 0;
  1583.     FILE *fp;
  1584.     int i;
  1585.     
  1586.     fp=fopen(file,"wb");
  1587.     if (fp==0) return 0;
  1588.  
  1589.     fwrite(&nfaces,1,sizeof(int),fp);
  1590.     
  1591.     for (i=0;i<nfaces;i++ )
  1592.         {
  1593.         fwrite(&faces[i].lm,sizeof(int),1,fp);
  1594.         fwrite(&faces[i].lmuv,sizeof(int),6,fp);
  1595.         }
  1596.  
  1597.     fwrite(&nlmpic,1,sizeof(int),fp);
  1598.     for( i=0;i<nlmpic;i++ )
  1599.     {
  1600.         fwrite(&lmpic[i]->sizex,sizeof(int),1,fp);
  1601.         fwrite(&lmpic[i]->sizey,sizeof(int),1,fp);
  1602.         fwrite(lmpic[i]->bmp,lmpic[i]->bytesxy,1,fp);
  1603.     }
  1604.  
  1605.     fwrite(&nlm,1,sizeof(int),fp);
  1606.     for( i=0;i<nlm;i++ )
  1607.         {
  1608.         fwrite(&lm[i]->facenum,sizeof(int),1,fp);
  1609.         fwrite(&lm[i]->pic,sizeof(int),1,fp);
  1610.         fwrite(&lm[i]->offsetx,sizeof(int),2,fp);
  1611.         fwrite(&lm[i]->sizex,sizeof(int),2,fp);
  1612.         }
  1613.  
  1614.     fclose(fp);
  1615.     return 1;
  1616. }
  1617.  
  1618. int flyEngine::load_pvs(char *file)
  1619. {
  1620.     int i;
  1621.     fly_pak fp;
  1622.  
  1623.     alloc_pvs((char)255);
  1624.     if (pvssize==0) return 0;
  1625.  
  1626.     if (!fp.open(file)) return 0;
  1627.  
  1628.     fp.read(&i,sizeof(int));
  1629.     if (i==nleaf)
  1630.         fp.read(pvs,pvssize);
  1631.     
  1632.     fp.close();
  1633.  
  1634.     for( i=0;i<nleaf;i++ )
  1635.         if (leaf[i]->leaf!=i)
  1636.             break;
  1637.  
  1638.     return 1;
  1639. }
  1640.  
  1641. int flyEngine::save_pvs(char *file)
  1642. {
  1643.     FILE *fp;
  1644.     if (pvssize==0) return 0;
  1645.     fp=fopen(file,"wb");
  1646.     if (fp==0) return 0;
  1647.     fwrite(&nleaf,1,sizeof(int),fp);
  1648.     fwrite(pvs,pvssize,1,fp);
  1649.     fclose(fp);
  1650.     return 1;
  1651. }
  1652.  
  1653. void WriteProfileInt(char *sec,char *key,int value)
  1654. {
  1655.     char str[256];
  1656.     sprintf(str,"%i",value);
  1657.     WriteProfileString(sec,key,str);
  1658. }
  1659.  
  1660. int GetProfileInt(char *sec,char *key,int value)
  1661. {
  1662.     char str[256];
  1663.     GetProfileString(sec,key,"",str,128);
  1664.     if (str[0]!=0)
  1665.         sscanf(str,"%i",&value);
  1666.     
  1667.     return value;
  1668. }
  1669.  
  1670. bsp_object *flyEngine::get_active_object(char *name)
  1671. {
  1672.     bsp_object *o=active_obj0;
  1673.     
  1674.     while(o)
  1675.         {
  1676.         if (!stricmp(name,o->name))
  1677.             break;
  1678.         o=(bsp_object *)o->next_obj;
  1679.         }
  1680.     
  1681.     return o;
  1682. }
  1683.  
  1684. bsp_object *flyEngine::get_stock_object(char *name)
  1685. {
  1686.     if (name[0]==0) return 0;
  1687.     bsp_object *o=stock_obj0;
  1688.     while(o)
  1689.         {
  1690.         if (!stricmp(name,o->name))
  1691.             break;
  1692.         o=(bsp_object *)o->next_obj;
  1693.         }
  1694.  
  1695.     return o;
  1696. }
  1697.  
  1698. bezier_curve *flyEngine::get_bezier_curve(char *name)
  1699. {
  1700.     if (name[0]==0) return 0;
  1701.     bezier_curve *o=bezier_curve0;
  1702.     while(o)
  1703.         {
  1704.         if (!stricmp(name,o->name))
  1705.             break;
  1706.         o=(bezier_curve *)o->next_obj;
  1707.         }
  1708.  
  1709.     if (o==0)
  1710.         {
  1711.         char tmp[256];
  1712.         o=new bezier_curve;
  1713.         strcpy(o->name,name);
  1714.         strcpy(o->long_name,name);
  1715.         strcpy(tmp,flydatapath);
  1716.         strcat(tmp,"objects\\");
  1717.         strcat(tmp,name);
  1718.         if (o->load_bez(tmp)==0)
  1719.             {
  1720.             delete o;
  1721.             return 0;
  1722.             }
  1723.         o->next_obj=bezier_curve0;
  1724.         bezier_curve0=o;
  1725.         }
  1726.  
  1727.     return o;
  1728. }
  1729.  
  1730. bezier_patch *flyEngine::get_bezier_patch(char *name)
  1731. {
  1732.     if (name[0]==0) return 0;
  1733.     bezier_patch *o=bezier_patch0;
  1734.     while(o)
  1735.         {
  1736.         if (!stricmp(name,o->name))
  1737.             break;
  1738.         o=(bezier_patch *)o->next_obj;
  1739.         }
  1740.  
  1741.     if (o==0)
  1742.         {
  1743.         char tmp[256];
  1744.         o=new bezier_patch;
  1745.         strcpy(o->name,name);
  1746.         strcpy(o->long_name,name);
  1747.         strcpy(tmp,flydatapath);
  1748.         strcat(tmp,"objects\\");
  1749.         strcat(tmp,name);
  1750.         if (o->load_pch(tmp)==0)
  1751.             {
  1752.             delete o;
  1753.             return 0;
  1754.             }
  1755.         o->next_obj=bezier_patch0;
  1756.         bezier_patch0=o;
  1757.         }
  1758.  
  1759.     return o;
  1760. }
  1761.  
  1762. mesh *flyEngine::get_model_object(char *name)
  1763. {
  1764.     if (name[0]==0) return 0;
  1765.     mesh *o=model_obj0;
  1766.     while(o)
  1767.         {
  1768.         if (!stricmp(name,o->name))
  1769.             break;
  1770.         o=(mesh *)o->next_obj;
  1771.         }
  1772.  
  1773.     if (o==0)
  1774.         {
  1775.         if (strrchr(name,'.'))
  1776.             if (!stricmp(strrchr(name,'.'),".3ds"))
  1777.             {
  1778.             char tmp[256];
  1779.             o=new mesh;
  1780.             strcpy(o->name,name);
  1781.             strcpy(o->long_name,name);
  1782.             strcpy(tmp,flydatapath);
  1783.             strcat(tmp,"objects\\");
  1784.             strcat(tmp,name);
  1785.             if (o->load_3ds(tmp)==0)
  1786.                 {
  1787.                 delete o;
  1788.                 return 0;
  1789.                 }
  1790.             o->next_obj=model_obj0;
  1791.             model_obj0=o;
  1792.             }
  1793.             else
  1794.             if (!stricmp(strrchr(name,'.'),".fao"))
  1795.             {
  1796.             char tmp[256];
  1797.             o=new anim_mesh;
  1798.             strcpy(o->name,name);
  1799.             strcpy(o->long_name,name);
  1800.             strcpy(tmp,flydatapath);
  1801.             strcat(tmp,"objects\\");
  1802.             strcat(tmp,name);
  1803.             if (((anim_mesh *)o)->load_fao(tmp)==0)
  1804.                 {
  1805.                 delete o;
  1806.                 return 0;
  1807.                 }
  1808.             o->next_obj=model_obj0;
  1809.             model_obj0=o;
  1810.             }
  1811.         }
  1812.  
  1813.     return o;
  1814. }
  1815.  
  1816. sound *flyEngine::get_sound_object(char *name)
  1817. {
  1818.     if (name[0]==0) return 0;
  1819.     sound *s=sound_obj0;
  1820.     while(s)
  1821.         {
  1822.         if (!stricmp(name,s->name))
  1823.             break;
  1824.         s=(sound *)s->next_obj;
  1825.         }
  1826.  
  1827.     if (s==0)
  1828.         {
  1829.         if (strrchr(name,'.'))
  1830.             if (!stricmp(strrchr(name,'.'),".wav"))
  1831.             {
  1832.             char tmp[256];
  1833.             s=new sound;
  1834.             strcpy(s->name,name);
  1835.             strcpy(s->long_name,name);
  1836.             strcpy(tmp,flydatapath);
  1837.             strcat(tmp,"sounds\\");
  1838.             strcat(tmp,name);
  1839.             if (s->load_wav(tmp)==0)
  1840.                 {
  1841.                 delete s;
  1842.                 return 0;
  1843.                 }
  1844.             s->next_obj=sound_obj0;
  1845.             sound_obj0=s;
  1846.             }
  1847.         }
  1848.  
  1849.     return s;
  1850. }
  1851.  
  1852. bsp_object *flyEngine::get_next_stock_object(bsp_object *o,int type)
  1853. {
  1854.     if (o==0) 
  1855.         o=stock_obj0;
  1856.     else o=(bsp_object *)o->next_obj;
  1857.  
  1858.     while(o)
  1859.         {
  1860.         if (type==0 || type==o->type)
  1861.             break;
  1862.         o=(bsp_object *)o->next_obj;
  1863.         }
  1864.     
  1865.     return o;
  1866. }
  1867.  
  1868. bsp_object *flyEngine::get_next_active_object(bsp_object *o,int type)
  1869. {
  1870.     if (o==0) 
  1871.         o=active_obj0;
  1872.     else o=(bsp_object *)o->next_obj;
  1873.     
  1874.     while(o)
  1875.         {
  1876.         if (type==0 || type==o->type)
  1877.             break;
  1878.         o=(bsp_object *)o->next_obj;
  1879.         }
  1880.     
  1881.     return o;
  1882. }
  1883.  
  1884. void flyEngine::compute_node_light()
  1885. {
  1886.     int i,x,y;
  1887.     unsigned char *uc;
  1888.     vector point;
  1889.     bsp_node *node;
  1890.     light_map_pic *lmp;
  1891.  
  1892.     if (nlm==0)
  1893.     {
  1894.     for( i=0;i<nleaf;i++ )
  1895.         leaf[i]->color.vec(1,1,1,1);
  1896.     return;
  1897.     }
  1898.  
  1899.     for( i=0;i<nleaf;i++ )
  1900.         {
  1901.         leaf[i]->color.null();
  1902.         leaf[i]->leaf=0;
  1903.         }
  1904.  
  1905.     for( i=0;i<nlm;i++ )
  1906.     {
  1907.     lmp=lmpic[lm[i]->pic];
  1908.     for( y=0;y<lm[i]->sizey;y++ )
  1909.         {
  1910.         uc=&lmp->bmp[(y+lm[i]->offsety)*lmp->bytesx+lm[i]->offsetx];
  1911.         for( x=0;x<lm[i]->sizex;x++ )
  1912.             {
  1913.             lm[i]->map_point((float)x/lm[i]->sizex+1.0f/(lm[i]->sizex*2),(float)y/lm[i]->sizey+1.0f/(lm[i]->sizey*2),point);
  1914.             node=find_node(bsp,point,0);
  1915.             if (node)
  1916.                 {
  1917.                 node->color.x+=*(uc++);
  1918.                 node->color.y+=*(uc++);
  1919.                 node->color.z+=*(uc++);
  1920.                 node->leaf++;
  1921.                 }
  1922.             else uc+=3;
  1923.             }
  1924.         }
  1925.     }
  1926.  
  1927.     for( i=0;i<nleaf;i++ )
  1928.         {
  1929.         if (leaf[i]->leaf)
  1930.             leaf[i]->color/=leaf[i]->leaf*255.0f;
  1931.         leaf[i]->color.w=1.0f;
  1932.         leaf[i]->leaf=i;
  1933.         }
  1934. }
  1935.  
  1936. void flyEngine::load_level()
  1937. {
  1938.     char str[256];
  1939.  
  1940.     strcpy(str,flydatapath);
  1941.     strcat(str,bspfile);
  1942.     strcat(str,".tex");
  1943.     load_pictures(str);
  1944.  
  1945.     strcpy(str,flydatapath);
  1946.     strcat(str,bspfile);
  1947.     strcat(str,".bsp");
  1948.     load_bsp(str);
  1949.  
  1950.     strcpy(str,flydatapath);
  1951.     strcat(str,bspfile);
  1952.     strcat(str,".pvs");
  1953.     load_pvs(str);
  1954.  
  1955.     strcpy(str,flydatapath);
  1956.     strcat(str,bspfile);
  1957.     strcat(str,".lmp");
  1958.     load_lightmaps(str);
  1959. }
  1960.  
  1961. int flyEngine::load_data()
  1962. {
  1963.     char ret[256],str[256];
  1964.     int i,j;
  1965.     param_desc pd;
  1966.  
  1967.     fly_pak fly_file;
  1968.     if (!fly_file.open(flyfilename))
  1969.         return 0;
  1970.  
  1971.     fly_file.get_profile_string("fly", "bspfile", bspfile);
  1972.  
  1973.     load_level();
  1974.  
  1975.     j=get_global_param_desc(0,0);
  1976.     for( i=0;i<j;i++ )
  1977.     {
  1978.     get_global_param_desc(i,&pd);
  1979.     fly_file.get_profile_string("fly",pd.name,ret);
  1980.     pd.set_string(ret);
  1981.     }
  1982.  
  1983.     if (fontspic!=-1)
  1984.         {
  1985.         strcpy(str,flydatapath);
  1986.         strcat(str,"maps\\");
  1987.         strcat(str,piclib[fontspic]->name);
  1988.         if (strrchr(str,'.'))
  1989.             *strrchr(str,'.')=0;
  1990.         strcat(str,".txt");
  1991.         fly_pak fp;
  1992.         if (fp.open(str))
  1993.             for( int i=0;i<64;i++ )
  1994.                 fonts_width[i]=fp.get_int();
  1995.         else 
  1996.             for( int i=0;i<64;i++ )
  1997.                 fonts_width[i]=FONTS_SIZE/2;
  1998.         }
  1999.  
  2000.     i=0;
  2001.     while(1)
  2002.         {
  2003.         sprintf(str,"dll%i",i++);
  2004.         fly_file.get_profile_string("classes",str,ret);
  2005.         if (ret[0]==0) break;
  2006.         dll.add_dll(ret);
  2007.         }
  2008.  
  2009.     dll.load_all_classes(&fly_file);
  2010.     bsp_object *o=active_obj0;
  2011.     while(o)
  2012.         {
  2013.         o->load_params(&fly_file,o->name);
  2014.         o=(bsp_object *)o->next_obj;
  2015.         }
  2016.     o=stock_obj0;
  2017.     while(o)
  2018.         {
  2019.         o->load_params(&fly_file,o->name);
  2020.         o=(bsp_object *)o->next_obj;
  2021.         }
  2022.  
  2023.     fly_file.get_profile_string("fly","camera",ret);
  2024.     cam=get_active_object(ret);
  2025.     fly_file.get_profile_string("fly","player",ret);
  2026.     player=get_active_object(ret);
  2027.     
  2028.     if (directx)
  2029.         directx->players[0].data=player;
  2030.  
  2031.     bsp_object *s=0,*n;
  2032.     o=stock_obj0;
  2033.     while(o)
  2034.         {
  2035.         n=(bsp_object *)o->next_obj;
  2036.         o->next_obj=s;
  2037.         s=o;
  2038.         o=n;
  2039.         }
  2040.         
  2041.     stock_obj0=s;
  2042.  
  2043.     o=stock_obj0;
  2044.     while(o)
  2045.         {
  2046.         cur_step++;
  2047.         o->init();
  2048.         o=(bsp_object *)o->next_obj;
  2049.         }
  2050.     o=active_obj0;
  2051.     while(o)
  2052.         {
  2053.         cur_step++;
  2054.         o->init();
  2055.         o->add_to_bsp();
  2056.         o=(bsp_object *)o->next_obj;
  2057.         }
  2058.  
  2059.     compute_node_light();
  2060.  
  2061.     dll.send_message(FLYM_INITSCENE,0,0);
  2062.  
  2063.     return 1;
  2064. }
  2065.  
  2066. int flyEngine::add_lightmap(int sx,int sy)
  2067. {
  2068.     int x=0,y=0,i,j;
  2069.     int sizes[]={ 1,2,4,8,16,32,64,128,256 };
  2070.     for( i=0,j=256;i<9;i++ )
  2071.         if (abs(sizes[i]-sx)<j)
  2072.             {
  2073.             j=abs(sizes[i]-sx);
  2074.             x=i;
  2075.             }
  2076.     for( i=0,j=256;i<9;i++ )
  2077.         if (abs(sizes[i]-sy)<j)
  2078.             {
  2079.             j=abs(sizes[i]-sy);
  2080.             y=i;
  2081.             }
  2082.  
  2083.     lmpic[nlmpic]=new light_map_pic(sizes[x],sizes[y],3);
  2084.     fmpic[nlmpic]=new light_map_pic(sizes[x],sizes[y],4);
  2085.     lm[nlm]=new light_map(-1,nlmpic,0,0,sizes[x],sizes[y],3);
  2086.     fm[nlm]=new light_map(-1,nlmpic,0,0,sizes[x],sizes[y],4);
  2087.  
  2088.     nlmpic++;
  2089.     return nlm++;
  2090. }
  2091.  
  2092. int flyEngine::get_obj_param(char *objname,char *param,char *value)
  2093. {
  2094.     value[0]=0;
  2095.     bsp_object *obj;
  2096.     obj=active_obj0;
  2097.     while(obj)
  2098.         {
  2099.         if (!stricmp(objname,obj->long_name))
  2100.             break;
  2101.         obj=(bsp_object *)obj->next_obj;
  2102.         }
  2103.     if (obj==0)
  2104.         {
  2105.         obj=stock_obj0;
  2106.         while(obj)
  2107.             {
  2108.             if (!stricmp(objname,obj->long_name))
  2109.                 break;
  2110.             obj=(bsp_object *)obj->next_obj;
  2111.             }
  2112.         }
  2113.     if (obj==0) return 1;
  2114.     int i,n;
  2115.     param_desc pd;
  2116.     n=obj->get_param_desc(0,0);
  2117.     for( i=0;i<n;i++ )
  2118.         {
  2119.         obj->get_param_desc(i,&pd);
  2120.         if (!stricmp(pd.name,param))
  2121.             break;
  2122.         }
  2123.     if (i==n)
  2124.         return 2;
  2125.  
  2126.     strcpy(value,pd.get_string());
  2127.  
  2128.     return 0;
  2129. }
  2130.  
  2131. int flyEngine::set_global_param(char *name,char *value)
  2132. {
  2133.     param_desc pd;
  2134.     int i,n;
  2135.  
  2136.     n=get_global_param_desc(0,0);
  2137.     for( i=0;i<n;i++ )
  2138.         {
  2139.         get_global_param_desc(i,&pd);
  2140.         if (!stricmp(name,pd.name))
  2141.             break;
  2142.         }
  2143.     if (i==n)
  2144.         return 0;
  2145.     
  2146.     pd.set_string(value);
  2147.     if (pd.type=='p' || pd.type=='3' || pd.type=='m')
  2148.     {
  2149.         close_texture_cache();
  2150.         init_texture_cache();
  2151.     }
  2152.  
  2153.     bsp_object *obj;
  2154.     obj=stock_obj0;
  2155.     while(obj)
  2156.     {
  2157.         obj->message(vector(0,0,0),0,FLYOBJM_CHANGEPARAM,-i-1,&pd);
  2158.         obj=(bsp_object *)obj->next_obj;
  2159.     }
  2160.     obj=active_obj0;
  2161.     while(obj)
  2162.     {
  2163.         obj->message(vector(0,0,0),0,FLYOBJM_CHANGEPARAM,-i-1,&pd);
  2164.         obj=(bsp_object *)obj->next_obj;
  2165.     }
  2166.  
  2167.     return 1;
  2168. }
  2169.  
  2170. int flyEngine::set_obj_param(char *objname,char *param,char *value)
  2171. {
  2172.     bsp_object *obj=stock_obj0;
  2173.     int ret=0;
  2174.     while(obj)
  2175.         {
  2176.         if (!stricmp(objname,obj->long_name))
  2177.             break;
  2178.         obj=(bsp_object *)obj->next_obj;
  2179.         }
  2180.     if (obj==0) return 1;
  2181.  
  2182.     param_desc pd;
  2183.     int i,j,n;
  2184.     n=obj->get_param_desc(0,0);
  2185.     for( i=0;i<n;i++ )
  2186.         {
  2187.         obj->get_param_desc(i,&pd);
  2188.         if (!stricmp(pd.name,param))
  2189.             break;
  2190.         }
  2191.     if (i==n)
  2192.         return 2;
  2193.  
  2194.     j=4;
  2195.     if (pd.type=='d' || pd.type<-255)
  2196.     {
  2197.         bsp_object *o=active_obj0;
  2198.         while(o)
  2199.         {
  2200.             if (!stricmp(o->long_name,value))
  2201.                 break;
  2202.             o=(bsp_object *)o->next_obj;
  2203.         }
  2204.         *((bsp_object **)pd.data)=o;
  2205.     }
  2206.     else
  2207.     if (pd.type=='o' || pd.type>255)
  2208.     {
  2209.         bsp_object *o=stock_obj0;
  2210.         while(o)
  2211.         {
  2212.             if (!stricmp(o->long_name,value))
  2213.                 break;
  2214.             o=(bsp_object *)o->next_obj;
  2215.         }
  2216.         *((bsp_object **)pd.data)=o;
  2217.     }
  2218.     else pd.set_string(value);
  2219.  
  2220.     switch(pd.type)
  2221.     {
  2222.     case 'i':
  2223.     case 'f':
  2224.     case 'a':
  2225.     case 'w':
  2226.     case 'd':
  2227.     case 'o':
  2228.     case 'z':
  2229.     case 'h':
  2230.         break;
  2231.     case 'v':
  2232.     case 'c':
  2233.         j=12;
  2234.         break;
  2235.     case 's':
  2236.         j=strlen(value)+1;
  2237.         break;
  2238.     case 'p':
  2239.     case '3':
  2240.     case 'm':
  2241.         close_texture_cache();
  2242.         init_texture_cache();
  2243.         break;
  2244.     default:
  2245.         return 3;
  2246.     }
  2247.  
  2248.     obj->message(vector(0,0,0),0,FLYOBJM_CHANGEPARAM,0,0);
  2249.     char *data=(char *)pd.data;
  2250.     obj=active_obj0;
  2251.     while(obj)
  2252.         {
  2253.         if (!stricmp(objname,obj->long_name))
  2254.             {
  2255.             obj->get_param_desc(i,&pd);
  2256.             memcpy(pd.data,data,j);
  2257.             obj->message(vector(0,0,0),0,FLYOBJM_CHANGEPARAM,i,&pd);
  2258.             }
  2259.         obj=(bsp_object *)obj->next_obj;
  2260.         }
  2261.     
  2262.     return ret;
  2263. }
  2264.  
  2265. int flyEngine::get_global_param_desc(int i,param_desc *pd)
  2266. {
  2267.     if (pd!=0)
  2268.     switch(i)
  2269.     {
  2270.         case 0:
  2271.             pd->type='c';
  2272.             pd->data=&background;
  2273.             strcpy(pd->name,"background");
  2274.             break;
  2275.         case 1:
  2276.             pd->type='b';
  2277.             pd->data=&bspfile;
  2278.             strcpy(pd->name,"bspfile");
  2279.             break;
  2280.         case 2:
  2281.             pd->type='f';
  2282.             pd->data=&viewmindist;
  2283.             strcpy(pd->name,"viewmindist");
  2284.             break;
  2285.         case 3:
  2286.             pd->type='f';
  2287.             pd->data=&viewmaxdist;
  2288.             strcpy(pd->name,"viewmaxdist");
  2289.             break;
  2290.         case 4:
  2291.             pd->type='f';
  2292.             pd->data=&camangle;
  2293.             strcpy(pd->name,"camangle");
  2294.             break;
  2295.         case 5:
  2296.             pd->type='d';
  2297.             pd->data=&cam;
  2298.             strcpy(pd->name,"camera");
  2299.             break;
  2300.         case 6:
  2301.             pd->type='d';
  2302.             pd->data=&player;
  2303.             strcpy(pd->name,"player");
  2304.             break;
  2305.  
  2306.         case 7:
  2307.             pd->type=' ';
  2308.             pd->data=0;
  2309.             strcpy(pd->name,"");
  2310.             break;
  2311.  
  2312.         case 8:
  2313.             pd->type='i';
  2314.             pd->data=&amblight;
  2315.             strcpy(pd->name,"amblight");
  2316.             break;
  2317.         case 9:
  2318.             pd->type='f';
  2319.             pd->data=&curveerr;
  2320.             strcpy(pd->name,"curveerr");
  2321.             break;
  2322.         case 10:
  2323.             pd->type='f';
  2324.             pd->data=&geomdetail;
  2325.             strcpy(pd->name,"geomdetail");
  2326.             break;
  2327.         case 11:
  2328.             pd->type='f';
  2329.             pd->data=&lmpxsize;
  2330.             strcpy(pd->name,"lmpxsize");
  2331.             break;
  2332.         case 12:
  2333.             pd->type='i';
  2334.             pd->data=&mapmode;
  2335.             strcpy(pd->name,"mapmode");
  2336.             break;
  2337.         case 13:
  2338.             pd->type='i';
  2339.             pd->data=&mpdelay;
  2340.             strcpy(pd->name,"mpdelay");
  2341.             break;
  2342.         case 14:
  2343.             pd->type='c';
  2344.             pd->data=&shadowcolor;
  2345.             strcpy(pd->name,"shadowcolor");
  2346.             break;
  2347.         case 15:
  2348.             pd->type='f';
  2349.             pd->data=&shadowdepth;
  2350.             strcpy(pd->name,"shadowdepth");
  2351.             break;
  2352.  
  2353.         case 16:
  2354.             pd->type=' ';
  2355.             pd->data=0;
  2356.             strcpy(pd->name,"");
  2357.             break;
  2358.  
  2359.         case 17:
  2360.             pd->type='p';
  2361.             pd->data=&consolepic;
  2362.             strcpy(pd->name,"consolepic");
  2363.             break;
  2364.         case 18:
  2365.             pd->type='p';
  2366.             pd->data=&fontspic;
  2367.             strcpy(pd->name,"fontspic");
  2368.             break;
  2369.         case 19:
  2370.             pd->type='p';
  2371.             pd->data=&intropic;
  2372.             strcpy(pd->name,"intropic");
  2373.             break;
  2374.         case 20:
  2375.             pd->type='p';
  2376.             pd->data=&crosshairpic;
  2377.             strcpy(pd->name,"crosshairpic");
  2378.             break;
  2379.         case 21:
  2380.             pd->type='i';
  2381.             pd->data=&crosshairsize;
  2382.             strcpy(pd->name,"crosshairsize");
  2383.             break;
  2384.         case 22:
  2385.             pd->type='p';
  2386.             pd->data=&cartoonpicbsp;
  2387.             strcpy(pd->name,"cartoonpicbsp");
  2388.             break;
  2389.         case 23:
  2390.             pd->type='p';
  2391.             pd->data=&cartoonpic;
  2392.             strcpy(pd->name,"cartoonpic");
  2393.             break;
  2394.         case 24:
  2395.             pd->type='c';
  2396.             pd->data=&cartooncolor;
  2397.             strcpy(pd->name,"cartooncolor");
  2398.             break;
  2399.         case 25:
  2400.             pd->type='f';
  2401.             pd->data=&cartoonwidth;
  2402.             strcpy(pd->name,"cartoonwidth");
  2403.             break;
  2404.         case 26:
  2405.             pd->type='p';
  2406.             pd->data=&detailpic;
  2407.             strcpy(pd->name,"detailpic");
  2408.             break;
  2409.         case 27:
  2410.             pd->type='f';
  2411.             pd->data=&detailtile;
  2412.             strcpy(pd->name,"detailtile");
  2413.             break;
  2414.  
  2415.         case 28:
  2416.             pd->type=' ';
  2417.             pd->data=0;
  2418.             strcpy(pd->name,"");
  2419.             break;
  2420.  
  2421.         case 29:
  2422.             pd->type='i';
  2423.             pd->data=&antialias;
  2424.             strcpy(pd->name,"antialias");
  2425.             break;
  2426.         case 30:
  2427.             pd->type='i';
  2428.             pd->data=&clearbk;
  2429.             strcpy(pd->name,"clearbk");
  2430.             break;
  2431.         case 31:
  2432.             pd->type='i';
  2433.             pd->data=&fog;
  2434.             strcpy(pd->name,"fog");
  2435.             break;
  2436.         case 32:
  2437.             pd->type='i';
  2438.             pd->data=&hwlights;
  2439.             strcpy(pd->name,"hwlights");
  2440.             break;
  2441.         case 33:
  2442.             pd->type='i';
  2443.             pd->data=&mouse;
  2444.             strcpy(pd->name,"mouse");
  2445.             break;
  2446.         case 34:
  2447.             pd->type='i';
  2448.             pd->data=&mipmap;
  2449.             strcpy(pd->name,"mipmap");
  2450.             break;
  2451.         case 35:
  2452.             pd->type='i';
  2453.             pd->data=&multitexture;
  2454.             strcpy(pd->name,"multitexture");
  2455.             break;
  2456.         case 36:
  2457.             pd->type='i';
  2458.             pd->data=&mute;
  2459.             strcpy(pd->name,"mute");
  2460.             break;
  2461.         case 37:
  2462.             pd->type='i';
  2463.             pd->data=&nodeonly;
  2464.             strcpy(pd->name,"nodeonly");
  2465.             break;
  2466.         case 38:
  2467.             pd->type='i';
  2468.             pd->data=&pvsoff;
  2469.             strcpy(pd->name,"pvsoff");
  2470.             break;
  2471.         case 39:
  2472.             pd->type='i';
  2473.             pd->data=&shadows;
  2474.             strcpy(pd->name,"shadows");
  2475.             break;
  2476.         case 40:
  2477.             pd->type='i';
  2478.             pd->data=&status;
  2479.             strcpy(pd->name,"status");
  2480.             break;
  2481.         case 41:
  2482.             pd->type='i';
  2483.             pd->data=&stencil;
  2484.             strcpy(pd->name,"stencil");
  2485.             break;
  2486.         case 42:
  2487.             pd->type='i';
  2488.             pd->data=&textfilter;
  2489.             strcpy(pd->name,"textfilter");
  2490.             break;
  2491.         case 43:
  2492.             pd->type='i';
  2493.             pd->data=&wireframe;
  2494.             strcpy(pd->name,"wireframe");
  2495.             break;
  2496.     }
  2497.     return 44;
  2498. }
  2499.  
  2500.